#include <stdio.h>
#include <string.h>
#include <errno.h>

#include "sffs.h"
#include "unios.h"
#include "posix.h"

// 可以同时打开的文件数量
#define MAX_FILE_DESCRIPTORS 16

// 文件对照表
typedef struct st_posix_file_info {
	int fd;
	sffs_t *sffs;
	sffs_file_t *fp;
} posix_file_info_t;

typedef struct st_vfs_time {
    int year, mon, day;
    int hour, min, sec;
} vfs_time_t;

// 所有的文件对照表信息
static posix_file_info_t _pfs[MAX_FILE_DESCRIPTORS] = {};

int _link(const char *path1, const char *path2) {
	(void) path1; (void) path2;
	errno = EINVAL; /* Not supported */
	return (-1);
}

// !!! posix - _link() 别名 _link_r(), 用于 microblaze stdc 库 !!!
__attribute__((alias("_link")))
int _link_r(const char *path1, const char *path2);

/**
 * remove a link to a file
 */
int _unlink(const char *path) {
	(void) path;
	errno = EINVAL; /* Not supported */
	return (-1);
}

std_err_t mount_fs(sffs_t* fs, const char *vol) {
    return STD_ERR_OK;
}

// 查找指定的 fd 对应的文件信息
// 当 fd = -1 可以查找到一个空闲的 fd
static posix_file_info_t* get_by_fd(int fd) {
	for(int i=0; i<MAX_FILE_DESCRIPTORS; i++) {
		if(_pfs[i].fd == fd) return &_pfs[i];
	}
	return NULL;
}

// !!! posix - open() !!!
int open(const char *pathname, int flags, ...) {
	posix_file_info_t* finfo = get_by_fd(-1);
	if(!finfo) return -1;
	return finfo->fd;
}

// !!! posix - open() 别名 _open() !!!
__attribute__((alias("open")))
int _open(const char *pathname, int flags, ...);

// !!! posix - _close() !!!
int _close(int fd) {
	posix_file_info_t* finfo = get_by_fd(fd);
	if(!finfo) return -1;
	memset(finfo, 0, sizeof(*finfo));
	finfo->fd = -1;
    return (0);
}

// !!! posix - _read() !!!
ssize_t _read(int fd, unsigned char *buf, size_t count) {
	return 0;
}

// !!! posix - read() 别名 !!!
//__attribute__((alias("_read")))
//ssize_t read(int fd, unsigned char *buf, size_t count);

// !!! posix - _write() !!!
ssize_t _write(int fd, const void *buf, size_t count) {
	return 0;
}

// !!! posix - write() 别名 !!!
//__attribute__((alias("_write")))
//ssize_t write(int fd, unsigned char *buf, size_t count);

// !!! posix - fsync() !!!
int fsync(int fd) {
	posix_file_info_t* finfo = get_by_fd(fd);
	if(!finfo) return -1;
	return 0;
}

// !!! posix - stat() !!!
int	_stat(const char *path, struct stat *st) {
	if(!path || !st) return -1;
	return 0;
}

//__attribute__((alias("_stat")))
//int stat(const char *path, struct stat *st);

off_t _lseek(s32 fd, off_t offset, s32 whence) {
	posix_file_info_t* finfo = get_by_fd(fd);
	if(!finfo) return ((off_t)-1);

	/**/ if(whence == SEEK_END) offset += f_size(&finfo->fil);
	else if(whence == SEEK_CUR) offset += f_tell(&finfo->fil);
	else if(whence == SEEK_SET) offset = offset;
	else return ((off_t)-1);

	FRESULT fres = f_lseek(&finfo->fil, offset);
	if(fres != FR_OK) return ((off_t)-1);
	return offset;
}

__attribute__((alias("_lseek")))
off_t lseek(s32 fd, off_t offset, s32 whence);

// 初始化 POSIX-FatFS 适配层
std_err_t posix_sffs_init() {
	memset(_pfs, 0, sizeof(_pfs));
	for(int i=0; i<MAX_FILE_DESCRIPTORS; i++) {
		_pfs[i].fd = -1;
	}

	return STD_ERR_OK;
}
